#include <map>
#include <string>
#include <dirent.h>
#include <string.h>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

#include "screen.h"
#include "exception.h"


static SDL_Surface *sfScreen;
static std::map<std::string,SDL_Surface*> cache;
static TTF_Font *font = 0;
static rgb_t textColor;
static u8 textAlign = screen::HA_LEFT|screen::VA_TOP;


static void loadData()
{
  DIR *dp = opendir("data");
  if(!dp) throw exception("Couldn't open data directory!\n");

  dirent *entry;
  while((entry=readdir(dp)))
  {
    if(!strcmp(entry->d_name, ".")||!strcmp(entry->d_name, "..")) continue;

    std::string name = entry->d_name;
    size_t pos = name.rfind('.');
    if(pos==std::string::npos) continue; // no file extension

    std::string ext = name.substr(pos);
    if(ext==".png")
    {
      name = name.substr(0, pos);
      cache[name] = IMG_Load((std::string("data/")+name+".png").c_str());
      if(!cache[name]) throw exception(std::string("Couldn't load file: ")+name+".png");
      continue;
    }
    if(ext==".TTF")
    {
      if(font) continue; // font already loaded
      name = name.substr(0, pos);
      font = TTF_OpenFont((std::string("data/")+name+".TTF").c_str(), 24);
      if(!font) throw exception(std::string("Couldn't load file: ")+name+".TTF");
      continue;
    }
  }

  if(!font) throw exception("No font could be found!");

  closedir(dp);
}

int screen::init()
{
  /* be sure window is centered on screen */
  putenv("SDL_VIDEO_CENTERED=1");

  Uint32 flags = SDL_HWSURFACE|SDL_DOUBLEBUF;
  // flags |= SDL_FULLSCREEN;
  sfScreen = SDL_SetVideoMode(480, 320, 32, flags);

  if(!sfScreen) throw exception(std::string("SDL internal error: ")+SDL_GetError());

  SDL_WM_SetCaption("Simply Pong", "Simply Pong");

  loadData();

  return 0;
}


void screen::update()
{
  SDL_Flip(sfScreen);
  SDL_Delay(1000/30);
  SDL_FillRect(sfScreen, 0, 0x000000);
}


void screen::drawSprite(const char *name, int x, int y)
{
  SDL_Surface *&sf = cache[name];
  if(!sf) return;

  SDL_Rect drect;
  drect.x = x;
  drect.y = y;
  SDL_BlitSurface(sf, 0, sfScreen, &drect);
}

void screen::drawText(const char *text, int x, int y)
{
  SDL_Color color;
  color.r = textColor.r;
  color.g = textColor.g;
  color.b = textColor.b;
  SDL_Surface *sf = TTF_RenderText_Blended(font, text, color);
  if(!sf) return;

  SDL_Rect drect;
  drect.x = x;
  drect.y = y;

  // apply text align
  if(textAlign&HA_RIGHT) drect.x -= sf->w;
  else if(textAlign&HA_CENTER) drect.x -= sf->w/2;
  if(textAlign&VA_BOTTOM) drect.y -= sf->h;
  else if(textAlign&VA_MIDDLE) drect.y -= sf->h/2;

  // draw
  SDL_BlitSurface(sf, 0, sfScreen, &drect);
  SDL_FreeSurface(sf);
}

void screen::setTextColor(rgb_t color)
{
  textColor = color;
}

void screen::setTextAlign(u8 align)
{
  textAlign = align;
}
